﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Services.Contracts;
using System.Media;
using System.Threading.Tasks;
using System.Threading;

namespace UI.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        #region Member Variables

        const int PageSize = 10;
        readonly ITranslator _translator;
        readonly ISpeaker _speaker;
        readonly string[] _story;
        ObservableCollection<string> _phrases;
        private string _selectedPhrase;
        private string _translation;
        private Task<string> _translationTask;
        private int _currentPageIndex;
        private readonly int _totalCount;

        #endregion

        #region Constructor

        public MainWindowViewModel(ITranslator translator, ISpeaker speaker)
        {
            _translator = translator;
            _speaker = speaker;
            _story = UI.Resources.story.Split(new string[1] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            _totalCount = (int)Math.Ceiling((double)_story.Length / (double)PageSize);
            CurrentPageIndex = 1;
            LoadPage();
        }

        #endregion

        #region Public Properties

        public int TotalCount
        {
            get { return _totalCount; }
        }

        public int CurrentPageIndex
        {
            get { return _currentPageIndex; }
            set
            {
                if (value >= 0 && value <= _totalCount)
                {
                    _currentPageIndex = value;
                    LoadPage();
                    OnPropertyChanged("CurrentPageIndex");
                }
            }
        }

        public string Translation
        {
            get { return _translation; }
            set
            {
                _translation = value;
                OnPropertyChanged("Translation");
            }
        }

        public string SelectedPhrase
        {
            get { return _selectedPhrase; }
            set
            {
                _selectedPhrase = value;
                OnPropertyChanged("SelectedPhrase");
            }
        }

        public ObservableCollection<string> Phrases
        {
            get { return _phrases; }
            set
            {
                _phrases = value;
                OnPropertyChanged("Phrases");
            }
        }

        #endregion

        #region Commands

        public ICommand GetFirstPage
        {
            get
            {
                return new RelayCommand((string obj) => CurrentPageIndex = 1, () => CheckCanGoBack());
            }
        }

        public ICommand GetPreviousPage
        {
            get
            {
                return new RelayCommand((string obj) => CurrentPageIndex--, () => CheckCanGoBack());
            }
        }

        public ICommand GetNextPage
        {
            get
            {
                return new RelayCommand((string obj) => CurrentPageIndex++, () => CheckCanGoForward());
            }
        }

        public ICommand GetLastPage
        {
            get
            {
                return new RelayCommand((string obj) => CurrentPageIndex = TotalCount, () => CheckCanGoForward());
            }
        }

        public ICommand Translate
        {
            get
            {
                return new RelayCommand(TranslateExecute, () => true);
            }
        }

        #endregion

        #region Commands Methods

        private void TranslateExecute(string phrase)
        {
            if (SelectedPhrase != phrase)
            {
                SelectedPhrase = phrase;

                _translationTask = new Task<string>(() => _translator.Translate(phrase));
                _translationTask.ContinueWith(t => Translation = _translationTask.Result);
                _translationTask.Start();
            }

            _speaker.Speak(phrase);
        }

        #endregion

        #region Private Methods

        private void LoadPage()
        {
            var currentPage = _story
                .Skip((CurrentPageIndex - 1) * PageSize)
                .Take(PageSize);
            Phrases = new ObservableCollection<string>(currentPage);
        }

        private bool CheckCanGoBack()
        {
            return CurrentPageIndex > 1;
        }

        private bool CheckCanGoForward()
        {
            return CurrentPageIndex < TotalCount;
        }

        #endregion
    }
}